home *** CD-ROM | disk | FTP | other *** search
/ PC PowerPlay 58 / pcpp58a.iso / extras / quake 3 source / Q3A_ToolSource.exe / Main / lightmaps.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-02  |  8.5 KB  |  375 lines

  1. #include "qbsp.h"
  2.  
  3.  
  4. /*
  5.  
  6.   Lightmap allocation has to be done after all flood filling and
  7.   visible surface determination.
  8.  
  9. */
  10.  
  11. int                    numSortShaders;
  12. mapDrawSurface_t    *surfsOnShader[MAX_MAP_SHADERS];
  13.  
  14.  
  15. int        allocated[LIGHTMAP_WIDTH];
  16.  
  17. int        numLightmaps = 1;
  18. int        c_exactLightmap;
  19.  
  20.  
  21. void PrepareNewLightmap( void ) {
  22.     memset( allocated, 0, sizeof( allocated ) );
  23.     numLightmaps++;
  24. }
  25.  
  26. /*
  27. ===============
  28. AllocLMBlock
  29.  
  30. returns a texture number and the position inside it
  31. ===============
  32. */
  33. qboolean AllocLMBlock (int w, int h, int *x, int *y)
  34. {
  35.     int        i, j;
  36.     int        best, best2;
  37.  
  38.     best = LIGHTMAP_HEIGHT;
  39.  
  40.     for ( i=0 ; i <= LIGHTMAP_WIDTH-w ; i++ ) {
  41.         best2 = 0;
  42.  
  43.         for (j=0 ; j<w ; j++) {
  44.             if (allocated[i+j] >= best) {
  45.                 break;
  46.             }
  47.             if (allocated[i+j] > best2) {
  48.                 best2 = allocated[i+j];
  49.             }
  50.         }
  51.         if (j == w)    {    // this is a valid spot
  52.             *x = i;
  53.             *y = best = best2;
  54.         }
  55.     }
  56.  
  57.     if (best + h > LIGHTMAP_HEIGHT) {
  58.         return qfalse;
  59.     }
  60.  
  61.     for (i=0 ; i<w ; i++) {
  62.         allocated[*x + i] = best + h;
  63.     }
  64.  
  65.     return qtrue;
  66. }
  67.  
  68.  
  69. /*
  70. ===================
  71. AllocateLightmapForPatch
  72. ===================
  73. */
  74. //#define LIGHTMAP_PATCHSHIFT
  75.  
  76. void AllocateLightmapForPatch( mapDrawSurface_t *ds ) {
  77.     int            i, j, k;
  78.     drawVert_t    *verts;
  79.     int            w, h;
  80.     int            x, y;
  81.     float        s, t;
  82.     mesh_t        mesh, *subdividedMesh, *tempMesh, *newmesh;
  83.     int            widthtable[LIGHTMAP_WIDTH], heighttable[LIGHTMAP_HEIGHT], ssize;
  84.  
  85.     verts = ds->verts;
  86.  
  87.     mesh.width = ds->patchWidth;
  88.     mesh.height = ds->patchHeight;
  89.     mesh.verts = verts;
  90.     newmesh = SubdivideMesh( mesh, 8, 999 );
  91.  
  92.     PutMeshOnCurve( *newmesh );
  93.     tempMesh = RemoveLinearMeshColumnsRows( newmesh );
  94.     FreeMesh(newmesh);
  95.  
  96.     ssize = samplesize;
  97.     if (ds->shaderInfo->lightmapSampleSize)
  98.         ssize = ds->shaderInfo->lightmapSampleSize;
  99.  
  100. #ifdef LIGHTMAP_PATCHSHIFT
  101.     subdividedMesh = SubdivideMeshQuads( tempMesh, ssize, LIGHTMAP_WIDTH-1, widthtable, heighttable);
  102. #else
  103.     subdividedMesh = SubdivideMeshQuads( tempMesh, ssize, LIGHTMAP_WIDTH, widthtable, heighttable);
  104. #endif
  105.  
  106.     w = subdividedMesh->width;
  107.     h = subdividedMesh->height;
  108.  
  109. #ifdef LIGHTMAP_PATCHSHIFT
  110.     w++;
  111.     h++;
  112. #endif
  113.  
  114.     FreeMesh(subdividedMesh);
  115.  
  116.     // allocate the lightmap
  117.     c_exactLightmap += w * h;
  118.  
  119.     if ( !AllocLMBlock( w, h, &x, &y ) ) {
  120.         PrepareNewLightmap();
  121.         if ( !AllocLMBlock( w, h, &x, &y ) ) {
  122.             Error("Entity %i, brush %i: Lightmap allocation failed", 
  123.                 ds->mapBrush->entitynum, ds->mapBrush->brushnum );
  124.         }
  125.     }
  126.  
  127. #ifdef LIGHTMAP_PATCHSHIFT
  128.     w--;
  129.     h--;
  130. #endif
  131.  
  132.     // set the lightmap texture coordinates in the drawVerts
  133.     ds->lightmapNum = numLightmaps - 1;
  134.     ds->lightmapWidth = w;
  135.     ds->lightmapHeight = h;
  136.     ds->lightmapX = x;
  137.     ds->lightmapY = y;
  138.  
  139.     for ( i = 0 ; i < ds->patchWidth ; i++ ) {
  140.         for ( k = 0 ; k < w ; k++ ) {
  141.             if ( originalWidths[k] >= i ) {
  142.                 break;
  143.             }
  144.         }
  145.         if (k >= w)
  146.             k = w-1;
  147.         s = x + k;
  148.         for ( j = 0 ; j < ds->patchHeight ; j++ ) {
  149.             for ( k = 0 ; k < h ; k++ ) {
  150.                 if ( originalHeights[k] >= j ) {
  151.                     break;
  152.                 }
  153.             }
  154.             if (k >= h)
  155.                 k = h-1;
  156.             t = y + k;
  157.             verts[i + j * ds->patchWidth].lightmap[0] = ( s + 0.5 ) / LIGHTMAP_WIDTH;
  158.             verts[i + j * ds->patchWidth].lightmap[1] = ( t + 0.5 ) / LIGHTMAP_HEIGHT;
  159.         }
  160.     }
  161. }
  162.  
  163.  
  164. /*
  165. ===================
  166. AllocateLightmapForSurface
  167. ===================
  168. */
  169. //#define    LIGHTMAP_BLOCK    16
  170. void AllocateLightmapForSurface( mapDrawSurface_t *ds ) {
  171.     vec3_t        mins, maxs, size, exactSize, delta;
  172.     int            i;
  173.     drawVert_t    *verts;
  174.     int            w, h;
  175.     int            x, y, ssize;
  176.     int            axis;
  177.     vec3_t        vecs[2];
  178.     float        s, t;
  179.     vec3_t        origin;
  180.     plane_t        *plane;
  181.     float        d;
  182.     vec3_t        planeNormal;
  183.  
  184.     if ( ds->patch ) {
  185.         AllocateLightmapForPatch( ds );
  186.         return;
  187.     }
  188.  
  189.     ssize = samplesize;
  190.     if (ds->shaderInfo->lightmapSampleSize)
  191.         ssize = ds->shaderInfo->lightmapSampleSize;
  192.  
  193.     plane = &mapplanes[ ds->side->planenum ];
  194.  
  195.     // bound the surface
  196.     ClearBounds( mins, maxs );
  197.     verts = ds->verts;
  198.     for ( i = 0 ; i < ds->numVerts ; i++ ) {
  199.         AddPointToBounds( verts[i].xyz, mins, maxs );
  200.     }
  201.  
  202.     // round to the lightmap resolution
  203.     for ( i = 0 ; i < 3 ; i++ ) {
  204.         exactSize[i] = maxs[i] - mins[i];
  205.         mins[i] = ssize * floor( mins[i] / ssize );
  206.         maxs[i] = ssize * ceil( maxs[i] / ssize );
  207.         size[i] = (maxs[i] - mins[i]) / ssize + 1;
  208.     }
  209.  
  210.     // the two largest axis will be the lightmap size
  211.     memset( vecs, 0, sizeof( vecs ) );
  212.  
  213.     planeNormal[0] = fabs( plane->normal[0] );
  214.     planeNormal[1] = fabs( plane->normal[1] );
  215.     planeNormal[2] = fabs( plane->normal[2] );
  216.  
  217.     if ( planeNormal[0] >= planeNormal[1] && planeNormal[0] >= planeNormal[2] ) {
  218.         w = size[1];
  219.         h = size[2];
  220.         axis = 0;
  221.         vecs[0][1] = 1.0 / ssize;
  222.         vecs[1][2] = 1.0 / ssize;
  223.     } else if ( planeNormal[1] >= planeNormal[0] && planeNormal[1] >= planeNormal[2] ) {
  224.         w = size[0];
  225.         h = size[2];
  226.         axis = 1;
  227.         vecs[0][0] = 1.0 / ssize;
  228.         vecs[1][2] = 1.0 / ssize;
  229.     } else {
  230.         w = size[0];
  231.         h = size[1];
  232.         axis = 2;
  233.         vecs[0][0] = 1.0 / ssize;
  234.         vecs[1][1] = 1.0 / ssize;
  235.     }
  236.  
  237.     if ( !plane->normal[axis] ) {
  238.         Error( "Chose a 0 valued axis" );
  239.     }
  240.  
  241.     if ( w > LIGHTMAP_WIDTH ) {
  242.         VectorScale ( vecs[0], (float)LIGHTMAP_WIDTH/w, vecs[0] );
  243.         w = LIGHTMAP_WIDTH;
  244.     }
  245.     
  246.     if ( h > LIGHTMAP_HEIGHT ) {
  247.         VectorScale ( vecs[1], (float)LIGHTMAP_HEIGHT/h, vecs[1] );
  248.         h = LIGHTMAP_HEIGHT;
  249.     }
  250.     
  251.     c_exactLightmap += w * h;
  252.  
  253.     if ( !AllocLMBlock( w, h, &x, &y ) ) {
  254.         PrepareNewLightmap();
  255.         if ( !AllocLMBlock( w, h, &x, &y ) ) {
  256.             Error("Entity %i, brush %i: Lightmap allocation failed", 
  257.                 ds->mapBrush->entitynum, ds->mapBrush->brushnum );
  258.         }
  259.     }
  260.  
  261.     // set the lightmap texture coordinates in the drawVerts
  262.     ds->lightmapNum = numLightmaps - 1;
  263.     ds->lightmapWidth = w;
  264.     ds->lightmapHeight = h;
  265.     ds->lightmapX = x;
  266.     ds->lightmapY = y;
  267.  
  268.     for ( i = 0 ; i < ds->numVerts ; i++ ) {
  269.         VectorSubtract( verts[i].xyz, mins, delta );
  270.         s = DotProduct( delta, vecs[0] ) + x + 0.5;
  271.         t = DotProduct( delta, vecs[1] ) + y + 0.5;
  272.         verts[i].lightmap[0] = s / LIGHTMAP_WIDTH;
  273.         verts[i].lightmap[1] = t / LIGHTMAP_HEIGHT;
  274.     }
  275.  
  276.     // calculate the world coordinates of the lightmap samples
  277.  
  278.     // project mins onto plane to get origin
  279.     d = DotProduct( mins, plane->normal ) - plane->dist;
  280.     d /= plane->normal[ axis ];
  281.     VectorCopy( mins, origin );
  282.     origin[axis] -= d;
  283.  
  284.     // project stepped lightmap blocks and subtract to get planevecs
  285.     for ( i = 0 ; i < 2 ; i++ ) {
  286.         vec3_t    normalized;
  287.         float    len;
  288.  
  289.         len = VectorNormalize( vecs[i], normalized );
  290.         VectorScale( normalized, (1.0/len), vecs[i] );
  291.         d = DotProduct( vecs[i], plane->normal );
  292.         d /= plane->normal[ axis ];
  293.         vecs[i][axis] -= d;
  294.     }
  295.  
  296.     VectorCopy( origin, ds->lightmapOrigin );
  297.     VectorCopy( vecs[0], ds->lightmapVecs[0] );
  298.     VectorCopy( vecs[1], ds->lightmapVecs[1] );
  299.     VectorCopy( plane->normal, ds->lightmapVecs[2] );
  300. }
  301.  
  302. /*
  303. ===================
  304. AllocateLightmaps
  305. ===================
  306. */
  307. void AllocateLightmaps( entity_t *e ) {
  308.     int                i, j;
  309.     mapDrawSurface_t    *ds;
  310.     shaderInfo_t    *si;
  311.  
  312.     qprintf ("--- AllocateLightmaps ---\n");
  313.  
  314.  
  315.     // sort all surfaces by shader so common shaders will usually
  316.     // be in the same lightmap
  317.     numSortShaders = 0;
  318.  
  319.     for ( i = e->firstDrawSurf ; i < numMapDrawSurfs ; i++ ) {
  320.         ds = &mapDrawSurfs[i];
  321.         if ( !ds->numVerts ) {
  322.             continue;        // leftover from a surface subdivision
  323.         }
  324.         if ( ds->miscModel ) {
  325.             continue;
  326.         }
  327.         if ( !ds->patch ) {
  328.             VectorCopy( mapplanes[ds->side->planenum].normal, ds->lightmapVecs[2] );
  329.         }
  330.  
  331.         // search for this shader
  332.         for ( j = 0 ; j < numSortShaders ; j++ ) {
  333.             if ( ds->shaderInfo == surfsOnShader[j]->shaderInfo ) {
  334.                 ds->nextOnShader = surfsOnShader[j];
  335.                 surfsOnShader[j] = ds;
  336.                 break;
  337.             }
  338.         }
  339.         if ( j == numSortShaders ) {
  340.             if ( numSortShaders >= MAX_MAP_SHADERS ) {
  341.                 Error( "MAX_MAP_SHADERS" );
  342.             }
  343.             surfsOnShader[j] = ds;
  344.             numSortShaders++;
  345.         }
  346.     }
  347.     qprintf( "%5i unique shaders\n", numSortShaders );
  348.  
  349.     // for each shader, allocate lightmaps for each surface
  350.  
  351. //    numLightmaps = 0;
  352. //    PrepareNewLightmap();
  353.  
  354.     for ( i = 0 ; i < numSortShaders ; i++ ) {
  355.         si = surfsOnShader[i]->shaderInfo;
  356.  
  357.         for ( ds = surfsOnShader[i] ; ds ; ds = ds->nextOnShader ) {
  358.             // some surfaces don't need lightmaps allocated for them
  359.             if ( si->surfaceFlags & SURF_NOLIGHTMAP ) {
  360.                 ds->lightmapNum = -1;
  361.             } else if ( si->surfaceFlags & SURF_POINTLIGHT ) {
  362.                 ds->lightmapNum = -3;
  363.             } else {
  364.                 AllocateLightmapForSurface( ds );
  365.             }
  366.         }
  367.     }
  368.  
  369.     qprintf( "%7i exact lightmap texels\n", c_exactLightmap );
  370.     qprintf( "%7i block lightmap texels\n", numLightmaps * LIGHTMAP_WIDTH*LIGHTMAP_HEIGHT );
  371. }
  372.  
  373.  
  374.  
  375.